﻿using Magicodes.ExporterAndImporter.Excel;
using Microsoft.AspNetCore.Authorization;
using PHMEE.ToolKits;
using System.Linq.Dynamic.Core;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.IO;

namespace PHMEE.Admin
{

    public class MainenanceAdviceAppService : PHMEEAdminAppService, IMainenanceAdviceAppService
    {
        private readonly IMainenanceAdviceManager mainenanceAdviceManager;
        private readonly IMainenanceAdviceRepository mainenanceAdviceRepository;
        private readonly IExcelImporter excelImporter;

        public MainenanceAdviceAppService(IMainenanceAdviceManager mainenanceAdviceManager, IMainenanceAdviceRepository mainenanceAdviceRepository, IExcelImporter excelImporter)
        {
            this.mainenanceAdviceManager = mainenanceAdviceManager;
            this.mainenanceAdviceRepository = mainenanceAdviceRepository;
            this.excelImporter = excelImporter;
        }

        [Authorize(PHMEEAdminPermissions.MainenanceAdvices.Create)]
        public async Task<Guid> CreateMainenanceAdviceAsync(MainenanceAdviceCreateDto input)
        {

            var createMainenanceAdvice = await mainenanceAdviceManager.CreateMainenanceAdvice(input.Code);

            createMainenanceAdvice.Type = input.Type;

            createMainenanceAdvice.TypeEn = input.TypeEn;

            createMainenanceAdvice.Advice = input.Advice;

            createMainenanceAdvice.AdviceEn = input.AdviceEn;

            await mainenanceAdviceRepository.PhmeeCreate(createMainenanceAdvice);

            return createMainenanceAdvice.Id;

        }

        [Authorize(PHMEEAdminPermissions.MainenanceAdvices.Update)]
        public async Task UpdateMainenanceAdviceAsync(MainenanceAdviceUpdateDto input)
        {
            var query = await mainenanceAdviceRepository.PhmeeGetQuery();

            if (query.Any(item => item.Code == input.Code && item.Id != input.Id))
            {
                throw new UserFriendlyException(L[PHMEEDomainErrorCodes.MainenanceAdviceCodeAlreadyExist], PHMEEDomainErrorCodes.MainenanceAdviceCodeAlreadyExist).WithData("Code", input.Code);
            }

            var mainenanceAdvice = await mainenanceAdviceRepository.PhmeeGetById(input.Id);

            if (mainenanceAdvice == null)
            {
                throw new UserFriendlyException(L[PHMEEDomainErrorCodes.MainenanceAdviceNotFound], PHMEEDomainErrorCodes.MainenanceAdviceNotFound);
            }

            mainenanceAdvice.SetCode(input.Code);

            mainenanceAdvice.Type = input.Type;

            mainenanceAdvice.TypeEn = input.TypeEn;

            mainenanceAdvice.Advice = input.Advice;

            mainenanceAdvice.AdviceEn = input.AdviceEn;

            await mainenanceAdviceRepository.PhmeeUpdate(mainenanceAdvice);
        }

        [Authorize(PHMEEAdminPermissions.MainenanceAdvices.Delete)]
        public async Task DeleteMainenanceAdviceAsync(Guid id)
        {
            await mainenanceAdviceRepository.PhmeeDelete(id);
        }

        [Authorize(PHMEEAdminPermissions.MainenanceAdvices.Default)]
        public async Task<MainenanceAdviceDto> GetMainenanceAdviceByIdAsync(Guid id)
        {
            MainenanceAdvice mainenanceAdvice = await mainenanceAdviceRepository.PhmeeGetById(id);

            if (mainenanceAdvice == null)
            {
                throw new UserFriendlyException(L[PHMEEDomainErrorCodes.MainenanceAdviceNotFound], PHMEEDomainErrorCodes.MainenanceAdviceNotFound);
            }

            var mainenanceAdviceDto = ObjectMapper.Map<MainenanceAdvice, MainenanceAdviceDto>(mainenanceAdvice);

            return mainenanceAdviceDto;
        }

        [Authorize(PHMEEAdminPermissions.MainenanceAdvices.Default)]
        public async Task<PagedResultDto<MainenanceAdviceDto>> GetPagedMainenanceAdvicesAsync(MainenanceAdviceListDto input)
        {

            var query = await mainenanceAdviceRepository.PhmeeGetQuery();

            query = query.WhereIf(!string.IsNullOrEmpty(input.Code), item => item.Code.Contains(input.Code));
            query = query.OrderBy(input.Sorting ?? nameof(input.Code));

            var totalCount = query.Count();

            if (input.IsPaged)
            {
                query = query.PageBy(input.SkipCount, input.MaxResultCount);
            }

            var mainenanceAdvices = await AsyncExecuter.ToListAsync(query);

            var items = ObjectMapper.Map<List<MainenanceAdvice>, List<MainenanceAdviceDto>>(mainenanceAdvices);

            return new PagedResultDto<MainenanceAdviceDto>(totalCount, items);

        }

        /// <summary>
        /// Excel模板存放的目录都是Templates
        /// </summary>
        /// <returns></returns>
        public async Task<byte[]> GenerateTemplateAsync()
        {
            string directoryPathTemplates = Path.Combine(Directory.GetCurrentDirectory(), "Templates");

            DirectoryHelper.CreateIfNotExists(directoryPathTemplates);

            var filePath = Path.Combine(directoryPathTemplates, "维保建议模板.xlsx");

            var result = await excelImporter.GenerateTemplate<MainenanceAdviceImportDto>(filePath);

            var bytes = File.ReadAllBytes(filePath);

            return bytes;
        }

        public async Task<OperationResult> ImportTemplateAsync(byte[] bytes, string fileName)
        {
            var result = await excelImporter.ImportPhmeeExcelFile<MainenanceAdviceImportDto>(bytes, fileName);

            if (!string.IsNullOrEmpty(result.Item2))
            {
                return OperationResult.Fail(result.Item2);
            }

            List<MainenanceAdviceImportDto> importDtos = result.Item1.Data.ToList();

            List<MainenanceAdvice> entities = new List<MainenanceAdvice>();

            foreach (var importDto in importDtos)
            {
                var id = GuidGenerator.Create();

                MainenanceAdvice model = new MainenanceAdvice(id, importDto.Code);
                model.Type = importDto.Type;
                model.TypeEn = importDto.TypeEn;
                model.Advice = importDto.Advice;
                model.AdviceEn = importDto.AdviceEn;
                model.CreationTime = DateTime.Now;
                model.CreatorId = CurrentUser.Id;

                entities.Add(model);
            }

            List<MainenanceAdvice> entitiesExist = await mainenanceAdviceRepository.PhmeeGetAll();

            var existingPairs = entitiesExist.Select(item => new { item.Code }).ToList();

            entities = entities.Where(item => !existingPairs.Any(existing => existing.Code == item.Code)).ToList();

            await mainenanceAdviceRepository.PhmeeCreateMany(entities);

            return OperationResult.SuccessResult();
        }

    }
}
